[iOS] コンビニ探知アプリをARで作ってみました。
1 はじめに
今回は、最近作成したコンビニ探知アプリを紹介させて下さい。
画面下のボタンを押すと、現在地に最も近いコンビニを10件検索し、種類(アイコン)、距離、店舗名をARで表示します。画面を見ながら、(自分が)360度回ると近くのコンビニがどの方向に有るかを見ることが出来ます。
Google Mapなどで検索しても、結局どっちに向かって歩いて行けば良いのかオロオロする、超方向音痴な私のためのアプリです。
2 ARフレームワーク
今回も、ARのフレームワークには、Wikitudeを利用させて頂きました。 Wikitudeの導入に関しては、下記のページで既に紹介させて頂いておりますので、そちらを御覧ください。
参考 [iOS] AR(拡張現実)アプリ開発用SDK「Wikitude」のセットアップ手順
参考 [Xamarin.iOS] WikitudeでモバイルAR(拡張現実)アプリを作ってみた
3 コンビニの位置情報
GoogleAPIの位置情報サービスでコンビニの検索が可能です。
https://developers.google.com/places/web-service/search?hl=ja
この位置情報サービスでは、経度緯度を指定して、近隣の色々な施設の情報を検索できますが、typesにキーワードを指定することでコンビニだけを検索しています。
Google Place では、フレームワークを使用する方法もありますが、こちらでは、今回の目的とする対象(コンビニ)を指定しての検索に対応していなかったため、あえてブラウザから使用するWebAPIを使用しています。
(1) サービスの有効化
位置情報サービスを使用するには、最初にサービスの有効化が必要です。
GoogleAPIのコンソールから、Google Places API for iOS と Google Maps SDK for iOS を有効にします
https://console.developers.google.com/apis/library?project=arlocationsample
(2) APIキーの作成
続いて左の認証情報から「認証情報作成」から「APIキー」-「ブラウザキー」と辿りAPIキーを作成します。
作成が完了すると、一覧の中にキーが表示されます。
(3) 検索
WebAPIのエンドポイントと指定するパラメータは、次のとおりです。
https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=軽度,緯度&radius=距離(m)&types=convenience_store&key=APIキー
上記の検索で、常に20件のデータが返されます。
アプリでは、最初に距離を300mに設定して検索を開始し、20件を超えた場合は、最も近いコンビニが検索に漏れている可能性があるということで、距離を半分にしながら再帰的に検索しています。そして、逆に20件に満たない場合は、距離を倍にしていきます。
最後に、収集できたデータを距離でソートして、最も近隣の10件を得ています。
4 CocoaPodsでエラー
AFNetworking及びSVProgressHUDをCocoaPodsで利用させて頂いたのですが、pod installで下記のワーニングが出ました。
[!] The `ARLocationSample [Debug]` target overrides the `OTHER_LDFLAGS` build setting defined in `Pods/Target Support Files/Pods-ARLocationSample/Pods-ARLocationSample.debug.xcconfig'. This can lead to problems with the CocoaPods installation - Use the `$(inherited)` flag, or - Remove the build settings from the target.
どうやら、Wikitude使用するために、Other Linker Flags に -ObjC を設定しているのが影響したようです。 下記のように $(inherited) を追加することで、問題は解消しました。
参考:[iOS/Xcode/CocoaPods] pod install で OTHER_LDFLAGS が設定されない時
5 Objective-CからJavaScriptへのデータの受け渡し
Wikitudeでは、ロジック部分をObjective-CとJavaScriptのどちらでも書く事ができます。 好きな方でやればいいのですが、JavaScript弱者な私は、ほとんどのロジックをObjective-C側で書きました。 そして、Objective-Cから、JavaScriptへの受け渡しは、下記のようなコードになります。
まずは、受け渡すJsonデータを文字列で作成します。
//Json文字列の作成 - (NSString *) jsonData { NSMutableString *str = [NSMutableString string]; [str appendString: @"{\"convenienceStore\":["]; bool farst = true; for (ConvenienceStore *convenienceStore in _convenienceStores) { if(!farst) { [str appendString: @","]; } NSString *json = [NSString stringWithFormat:@"{ \"name\": \"%@\", \"latitude\": %f, \"longitude\": %f, \"altitude\": %f, \"distance\":\"%@\", \"grouping\": %ld }" ,convenienceStore.name, convenienceStore.latitude, convenienceStore.longitude, convenienceStore.altitude, convenienceStore.distanceStr, convenienceStore.grouping]; [str appendString: json]; farst = false; } [str appendString: @"]}"]; return str; }
次に、上記を引数としたJavaScriptのファンクションを文字列として作成して、wikitudeのオブジェクトでcallJavaScriptメソッドをコールします。
// JavaScriptへのデータ送信 NSString *jsonData = self.convenienceStoreRepository.jsonData; NSString *javascript = [NSString stringWithFormat:@"createData('%@')",jsonData]; [self.architectView callJavaScript:javascript];
JavaScript側では、引数の文字列絵を JSON.parse() でオブジェクト化して利用します。
function createData(json){ var data = JSON.parse(json); var convenienceStores = data.convenienceStore; }
6 最後に
一応、一通り動いているのですが・・・まだ、微妙にずれたりしてます。職場の方の話によると、コンパスの問題かな・・・?というアドバイスも頂きました。 引き続き、鍛えていきたいと思います。
また、友人が、HoloLens版を作ってみたいと話していたので、こちらも楽しみです。
コードは下記にあります。
[GitHub] https://github.com/furuya02/ConvenienceExplorer
(プロジェクト再構築に、Wikitude及びGoogle PlaceのAPIキーが必要です)
7 参考資料
Places API for iOS の使用を開始する
Wikitude 基となるPOIデータの取得方法
Wikitude Getting started
ネイティブコードとJavaScriptの連携となるサンプル
Wikitude サンプル